/*----------------------------------------------------------------------------------------
*
*  Copyright 2019, Gao Hai Hui, <fromzeropoint@126.com>.  All rights reserved.
*  https://gitee.com/helloworldghh/xoskit.git
*  Use of this source code is governed by a MIT license
*  that can be found in the License file.
*
----------------------------------------------------------------------------------------*/
#include "../import/head.h"
#include "../data_struct/head.h"
#include "err_info.h"
#include "mgr.h"

////////////////////////////////////////////////////////////////////////////////////////////
// 

namespace xos_odbc
{

    //////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

	err_info::err_info()
    {
    }

	err_info::~err_info()
    {
    }

    /////////////////////////////////////////////////////////////////////////////////////////////
    // public method

    const char * err_info::get_info( char * lpszInfo, int nSize, int * lpnInfoLen, int * lpnLenNeeded )
    {
        const char * lpszRet = m_str_info.c_str();
		int len = ( int )m_str_info.length();

		if( lpszInfo && ( nSize > len ) )
		{
			mgr::container()->crt()->strcpy( lpszInfo, nSize, m_str_info.c_str() );
		}

        if( lpnLenNeeded )
        {
            *lpnLenNeeded = len + 1;
        }

		if( lpnInfoLen )
		{
			*lpnInfoLen = len;
		}

        return lpszRet;
    }

    int err_info::get_info( SQLSMALLINT handle_type, SQLHANDLE handle )
    {
        using namespace std;
        int ret = 0;

        xos_box::i_string * pStrA = mgr::container()->box()->string();
        xos_box::i_buf * pBuf = mgr::container()->box()->buf();

        SQLWCHAR errstate[1024] = { 0 };
		SQLWCHAR errmsg[4096] = { 0 };
		SQLSMALLINT errmsglen = 0;
		SQLINTEGER errnative = 0;

		if( 0 == ret )
		{
            SQLRETURN retcode = SQLGetDiagRecW( handle_type, handle, 1, errstate, &errnative, errmsg, sizeof( errmsg ) / sizeof( errmsg[0] ), &errmsglen );
			if( SQL_SUCCESS != retcode )
			{
				ret = 1;
			}
		}

		if( 0 == ret )
		{
            const char * pErrMsg = (const char *)errmsg;
            int nLen = errmsglen * sizeof( int16_t );
            pBuf->add_data( pErrMsg, nLen, true );
            mgr::container()->misc()->utf16_to_utf8( pBuf, pStrA );
			m_str_info = pStrA->get(0,0);
		}
		else
		{
			m_str_info = "not get info";
		}

        xos_stl::release_interface( pStrA );
        xos_stl::release_interface( pBuf );

        return ret;
    }

    int err_info::connect_ret( SQLHANDLE handle, SQLRETURN sqlRet )
    {
        int ret = 0;
        ret = helper_ret( SQL_HANDLE_DBC, handle, sqlRet );
        return ret;
    }

    int err_info::stmt_ret( SQLHANDLE handle, SQLRETURN sqlRet )
    {
        int ret = 0;
        ret = helper_ret( SQL_HANDLE_STMT, handle, sqlRet );
        return ret;
    }

    int err_info::env_ret( SQLHANDLE handle, SQLRETURN sqlRet )
    {
        int ret = 0;
        ret = helper_ret( SQL_HANDLE_ENV, handle, sqlRet );
        return ret;
    }

	int err_info::clear()
	{
		int ret = 0;
		m_str_info = "success";
		return ret;
	}

    //////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 
    //  0 : success
    //  1 : pending
    //  2 : no data
    // -1 : failed
    // 
    int err_info::helper_ret( SQLSMALLINT handle_type, SQLHANDLE handle, SQLRETURN sqlRet )
    {
        int ret = -1;

        switch( sqlRet )
        {
        case SQL_INVALID_HANDLE:
        case SQL_ERROR:
            {
                clear();
                get_info( handle_type, handle );
                ret = -1;
            }
            break;
        case SQL_SUCCESS_WITH_INFO:
            {
                clear();
                get_info( handle_type, handle );
                ret = 0;
            }
            break;
        case SQL_SUCCESS:
            {
                ret = 0;
            }
            break;
        case SQL_NO_DATA:
            {
                ret = 2;
            }
            break;
        case SQL_STILL_EXECUTING:
            {
                ret = 1;
            }
            break;
        default:
            {
                ret = -1;
            }
            break;
        }

        return ret;
    }

} // xos_odbc
